package com.ug.system.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.ug.common.cache.redis.RedisCacheService;
import com.ug.common.constant.HotConstants;
import com.ug.common.enums.ErrorCode;
import com.ug.common.exception.SystemException;
import com.ug.common.utils.ThreadPoolUtil;
import com.ug.system.entity.AttributeValue;
import com.ug.system.entity.vo.HotToDayVO;
import com.ug.system.processor.HotToDayFactory;
import com.ug.system.service.HotToDayService;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;

import java.util.*;
import java.util.concurrent.*;

/**
 * @author: LY
 * @date: 2024/12/18 14:10
 * @description: 热点信息采集服务
 */
@Service
@RequiredArgsConstructor
public class HotToDayServiceImpl implements HotToDayService {

    private static final Logger logger = LoggerFactory.getLogger(HotToDayServiceImpl.class);
    private final RedisCacheService redisCacheService;
    private final HotToDayFactory hotToDayFactory;
    //  热点类型
    private final Map<String, String> hotMap = new HashMap<>(){{
        put(HotConstants.HOT_TYPE_BAIDU, "百度热搜");
        put(HotConstants.HOT_TYPE_BIBI, "B站热榜");
        put(HotConstants.HOT_TYPE_DOUYIN, "抖音热搜");
        put(HotConstants.HOT_TYPE_PENG_PAI, "澎湃新闻");
        put(HotConstants.HOT_TYPE_JUE_JIN, "掘金热榜");
        put(HotConstants.HOT_TYPE_WEIBO, "微博热搜");
        put(HotConstants.HOT_TYPE_TIBA, "贴吧热搜");
        put(HotConstants.HOT_TYPE_DOUBAN, "豆瓣电影一周口碑榜");
        put(HotConstants.HOT_TYPE_DOUBAN_BEIMEI, "豆瓣北美票房榜");
        put(HotConstants.HOT_TYPE_TOUTIAO, "头条热榜");
        put(HotConstants.HOT_TYPE_ZHIHU, "知乎热榜");
        put(HotConstants.HOT_TYPE_POJIE, "52破解热榜");
    }};

    @Override
    public List<HotToDayVO> getHotToDayList() {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        List<CompletableFuture<HotToDayVO>> futures = new ArrayList<>();
        List<HotToDayVO> hotToDayVOList = new ArrayList<>();
        for (Map.Entry<String, String> entry : hotMap.entrySet()){
            String channel = entry.getKey();
            String channelName = entry.getValue();
            CompletableFuture<HotToDayVO> hotToDayVOCompletableFuture = CompletableFuture.supplyAsync(() -> {
                try {
                    return getHotToDay(channel, channelName);
                } catch (Exception e) {
                    logger.warn("获取热点信息异常：{}", e.getMessage());
                }
                return null;
            }, ThreadPoolUtil.getInstance()).orTimeout(30, TimeUnit.SECONDS); // 单个任务超时设置为 10 秒
            futures.add(hotToDayVOCompletableFuture);
        }
        try {
            CompletableFuture<Void> allFutures = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allFutures.get(30, TimeUnit.SECONDS); // 整体超时设置为 20 秒

            for (CompletableFuture<HotToDayVO> future : futures) {
                try {
                    hotToDayVOList.add(future.join());
                } catch (Exception e) {
                    logger.warn("单个任务获取热点信息异常：{}", e.getCause().getMessage());
                }
            }
        } catch (InterruptedException | ExecutionException | TimeoutException e) {
            logger.error("获取热点信息整体异常：{}", e.getMessage());
        }
        stopWatch.stop();
        logger.info("耗时：{} 秒", stopWatch.getTotalTimeSeconds());
        return hotToDayVOList;
    }

    @Override
    public HotToDayVO getHotToDay(String hotName) {
        if (StrUtil.isEmpty(hotName) || !hotMap.containsValue(hotName)){
            throw new SystemException(ErrorCode.PARAMS_INVALID);
        }
        String channel = hotMap.entrySet().stream()
                .filter(entry -> entry.getValue().equals(hotName))
                .map(Map.Entry::getKey)
                .findFirst()
                .orElse(null);
        if (StrUtil.isEmpty(channel)){
            throw new SystemException(ErrorCode.PARAMS_INVALID);
        }
        return new HotToDayVO(hotName, hotToDayFactory.getHotToDayProcessor(channel), DateUtil.formatDateTime(new Date()));
    }

    /**
     * 获取热点数据
     * @param channel 渠道
     * @param channelName 渠道名称
     * @return 热点内容
     */
    public HotToDayVO getHotToDay(String channel, String channelName) {
        String key = channel.concat(HotConstants.HOT_TYPE_KEY);
        List<AttributeValue> hotToDayProcessor = (List<AttributeValue>) redisCacheService.getObject(key);
        if (hotToDayProcessor == null){
            hotToDayProcessor = hotToDayFactory.getHotToDayProcessor(channel);
        }
        return new HotToDayVO(channelName, hotToDayProcessor, DateUtil.formatDateTime(new Date()));
    }
}
